#include "../Renderer/Renderer.h"
#include "../external/external.h"
#include <string.h>
#include <iostream>

namespace Nitro::Renderer {

Pipeline CreatePipeline(const PipelineDescriptor& desc)
{
    Pipeline pipeline;
    glDebugMessageCallback([](auto, auto, auto, auto, auto , auto msg,
                              auto) { std::cout << msg << '\n'; },
                           0);
    pipeline.id = glCreateProgram();
    pipeline.drawMode = desc.drawMode;
    glAttachShader(pipeline.id, desc.vertexShader.id);
    glAttachShader(pipeline.id, desc.fragmentShader.id);
    glLinkProgram(pipeline.id);
    return pipeline;
}

bool Pipeline::hasReport()
{
    int status;
    glGetProgramiv(id, GL_LINK_STATUS, &status);
    return !status;
}

std::string Pipeline::getReport()
{
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));
    glGetProgramInfoLog(id, 1024, nullptr, buffer);
    return std::move(std::string(buffer));
}

void Pipeline::activate() { glUseProgram(id); }

void Pipeline::draw(int first, size_t count)
{
    glDrawArrays(drawMode, first, count);
}

void Pipeline::drawIndexed(const void* first, size_t count)
{
    glDrawElements(drawMode, count, GL_UNSIGNED_INT, (void*)first);
}

void Pipeline::setIndexBuffer(Buffer indexBuffer)
{
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.id);
}

void Pipeline::setVertexBuffer(Buffer vertexBuffer)
{
    glBindVertexArray(vertexBuffer.vao);
}

} // namespace Nitro::Renderer